package org.makcro.sms.services.chat.base.service;

import java.text.MessageFormat;
import java.util.Calendar;
import java.util.Date;

import org.apache.log4j.Logger;
import org.makcro.sms.services.chat.base.senders.MessageSender;
import org.makcro.sms.services.chat.model.BulkGroup;
import org.makcro.sms.services.chat.model.Question;

import com.klikmee.sms.core.commons.queues.EnqueueItemException;
import com.klikmee.sms.core.commons.queues.QueueItem;
import com.klikmee.sms.core.commons.queues.QueueManager;

public class SMSChatServiceImpl implements ChatService {

	/**
	 * Logger instance
	 */
	private Logger							logger					= Logger.getLogger( SMSChatServiceImpl.class );

	/**
	 * Constants used when processing delivery reports
	 */
	public static final String				ANSWER_DELIVERED		= "DELIVERED";
	public static final String				ANSWER_NOT_DELIVERED	= "NOT DELIVERED";

	/**
	 * Instance of message sender, responsible for handling message sending.
	 */
	private MessageSender					messageSender			= null;

	/**
	 * Response reports must be handled in queue.
	 */
	private QueueManager<ResponseReport>	responseReportQueueManager;

	/**
	 * Response reports have a validity. Number of hours is added to the time of
	 * putting into queue
	 */
	private int								deliveryReportValidityPeriod;

	/**
	 * Queue for pending questions
	 */
	private QueueManager<Question>			questionQueueManager;

	public void init() {

		// start response report queue manager
		this.responseReportQueueManager.start();
		this.questionQueueManager.start();
		logger.info( "SMS Chat service initialized." );
	}

	/**
	 * Service shutdown method
	 */
	public void shutDown() {
		// shutdown response report queue manager
		this.responseReportQueueManager.stop();
		this.questionQueueManager.stop();

		logger.info( "Chat service shutdown successfully" );
	}

	/**
	 * This method is invoked by web service on arrival of a service request.
	 * Saves new request message to database, and notifies any listeners of this
	 * event.
	 * 
	 * @param coreId
	 *            coreId of the message, later used to send response messages
	 * @param timeReceived
	 *            request reception time
	 * @param fromNumber
	 *            identifier of the sender of the message
	 * @param toNumber
	 *            number request was sent to, usually service's short code
	 * @param messageText
	 *            text of the message
	 */

	public void onRequestMessage(Long coreId, Date timeReceived, String fromNumber, String toNumber, String messageText) {

		// create question object and store it in db
		Question question = new Question();
		question.setCoreID( coreId );
		question.setDateReceived( timeReceived );
		question.setFromNumber( fromNumber );
		question.setQuestion( messageText );
		question.setToNumber( toNumber );
		// visibility omitted as it will be set by filters

		logger.debug( String.format( "Received new reqeust message coreId = [%s], from = [%s], text = [%s]", coreId, fromNumber, messageText ) );

		// create queue item
		QueueItem<Question> queueItem = new QueueItem<Question>( question );
		queueItem.setValidTo( new Date() ); // questions do not have validity
											// period for processing, it should
											// be instant

		// enqueue item
		try {
			this.questionQueueManager.enqueue( queueItem );
			logger.info( MessageFormat.format( "Enqueued new question from [{0}]", question.getFromNumber() ) );
		}
		catch (EnqueueItemException e) {
			logger.fatal( "Failed to enque question", e );
		}
		
	}

	/**
	 * Invoked on new response report. Creates queue item and put's it into
	 * queue.
	 */

	@Override
	public void onResponseReport(Long responseId, String status) {
		// create delivery report item
		ResponseReport responseReport = new ResponseReport( responseId, status );

		// create queue item
		QueueItem<ResponseReport> queueItem = new QueueItem<ResponseReport>( responseReport );
		// set items validity period
		Calendar currentTime = Calendar.getInstance();
		currentTime.add( Calendar.HOUR_OF_DAY, this.deliveryReportValidityPeriod );
		queueItem.setValidTo( currentTime.getTime() );

		// try to enqueue response report manager
		try {
			this.responseReportQueueManager.enqueue( queueItem );
			logger.debug( MessageFormat.format( "Enqueued status report for core reponse id [{0}]", responseId ) );
		}
		catch (EnqueueItemException e) {
			logger.fatal( MessageFormat.format( "Failed to enqueue response report for response [{0}]", responseId ), e );
		}

	}

	/**
	 * Invoked when new subscription to service occurs.
	 */

	public void onSubscriptionApproved(String distributionList, String subscriberId, Date validTo) {
		

	}

	@Override
	public void onSubscriptionExtension(String distributionListId, String msisdn, Date time) {
		

	}

	@Override
	public void onRemoveSubscription(String distributionListId, String msisdn) {
		

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.klikmee.sms.chat.web.service.ChatService#sendResponseMessage(java
	 * .lang.Long, java.lang.String)
	 */
	@Override
	public Long sendResponseMessage(Long referenceId, String messageText, Object data) {

		Long sendMessageResult = messageSender.sendMessage( messageText, referenceId, data );

		logger.info( String.format( "Response message with result = %s sent to the customer", sendMessageResult ) );
		return sendMessageResult;
	}

	/**
	 * Sends bulk message to the group of receivers
	 * 
	 * @param message
	 *            text of message
	 * @param group
	 *            group to send message to
	 * @param signatureText
	 * @return
	 */
	public int sendBulkMessage(String message, BulkGroup group, String signatureText) {
		// Collection<String> receivers = new LinkedList<String>();
		//
		// // itterate trough all items
		// for (BulkGroupItem item : group.getBulkGroupItemSet()) {
		// receivers.add(item.getPhoneNumber());
		// }
		//
		// int numberOfSentMessages =
		// this.coreAdapter.sendBulkMessage(this.bulkChargingId, this.serviceId,
		// receivers, message, signatureText);
		// return numberOfSentMessages;
		return 0;
	}

	/**
	 * Sens a bulk message to a single receiver
	 * 
	 * @param receiver
	 *            phone number of a receiver
	 * @param messageText
	 *            message text
	 * @return
	 */
	public int sendSingleBulk(String receiver, String messageText, String signatureText) {
		// Collection<String> receivers = new LinkedList<String>();
		// receivers.add(receiver);
		//
		// int numberOfSentMessages =
		// this.coreAdapter.sendBulkMessage(this.bulkChargingId, this.serviceId,
		// receivers, messageText, signatureText);
		// return numberOfSentMessages;
		return 0;
	}

	public void setMessageSender(MessageSender messageSender) {
		this.messageSender = messageSender;
	}

	public void setResponseReportQueueManager(QueueManager<ResponseReport> responseReportQueueManager) {
		this.responseReportQueueManager = responseReportQueueManager;
	}
	
	public void setDeliveryReportValidityPeriod(int deliveryReportValidityPeriod) {
		this.deliveryReportValidityPeriod = deliveryReportValidityPeriod;
	}
	
	public void setQuestionQueueManager(QueueManager<Question> questionQueueManager) {
		this.questionQueueManager = questionQueueManager;
	}
}
